package com.search.utils;

import com.alibaba.fastjson.JSON;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Xiongx
 * @version 1.0
 * @date 2021/8/4 10:16
 * @since JDK 1.8
 */
public class LuceneUtils {

    public static void createIndexData(Map<String, Object> stringObjectMap, String indexName){
        File file=getFilePath(indexName);

    }

    public static void indexSearch(String name) throws Exception{
        // 1. 创建分析器对象(Analyzer), 用于分词
        Analyzer analyzer = new StandardAnalyzer();

        // 2. 创建查询对象(Query)
        // 2.1 创建查询解析器对象
        // 参数一:默认的搜索域, 参数二:使用的分析器
        QueryParser queryParser = new QueryParser("title", analyzer);
        // 2.2 使用查询解析器对象, 实例化Query对象
        Query query = queryParser.parse("title:"+name);

        // 3. 创建索引库目录位置对象(Directory), 指定索引库位置
        Directory directory = FSDirectory.open(Paths.get("C:\\Users\\xiong\\Desktop\\index"));

        // 4. 创建索引读取对象(IndexReader), 用于读取索引
        IndexReader indexReader = DirectoryReader.open(directory);

        // 5. 创建索引搜索对象(IndexSearcher), 用于执行索引
        IndexSearcher searcher = new IndexSearcher(indexReader);

        // 6. 使用IndexSearcher对象执行搜索, 返回搜索结果集TopDocs
        // 参数一:使用的查询对象, 参数二:指定要返回的搜索结果排序后的前n个
        TopDocs topDocs = searcher.search(query, 10);

        // 7. 处理结果集
        // 7.1 打印实际查询到的结果数量
        System.out.println("实际查询到的结果数量: " + topDocs.totalHits);
        // 7.2 获取搜索的结果数组
        // ScoreDoc中有文档的id及其评分
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : scoreDocs) {
            System.out.println("= = = = = = = = = = = = = = = = = = =");
            // 获取文档的id和评分
            int docId = scoreDoc.doc;
            float score = scoreDoc.score;
            System.out.println("文档id= " + docId + " , 评分= " + score);
            // 根据文档Id, 查询文档数据 -- 相当于关系数据库中根据主键Id查询数据
            Document doc = searcher.doc(docId);
            System.out.println("图书Id: " + doc.get("title"));
        }

        // 8. 关闭资源
        indexReader.close();
    }



//    public static Page searchByKeyWord(String indexName,String field,String keyword,Integer total) throws Exception{
//        Page page=new Page();
//        IndexSearcher indexSearcher=createIndexSearcher(indexName);
//        TopDocs topDocs=getQueryDoc(indexSearcher,keyword,field,total);
//        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
//        List<Document> documents=getDocumentByScore(scoreDocs,indexSearcher);
//        List<Map<String, Object>> objectMaps=getDocumentArrayToMapArray(documents);
//
//        page.setContent(objectMaps);
//        //  page.setTotal(topDocs.totalHits);
//        return page;
//    }

    private static List<Map<String, Object>> subList(List<Map<String, Object>> mapList,Integer pageNum,Integer size){
        Integer page=(pageNum-1)*size;
        Integer mapSize=mapList.size();
        if(page<0){
            page=0;
        }else if(page>(mapSize-(size-1))){
            page=(mapSize-size);
        }
        return mapList.subList(page,size);
    }

    private static List<Map<String, Object>> getDocumentArrayToMapArray(List<Document> documentList){
        List<Map<String, Object>> mapList=new ArrayList<>(documentList.size());
        documentList.stream().forEach(e->{
            Map<String, Object> objectMap=getDocumentToMap(e);
            mapList.add(objectMap);
        });
        return mapList;
    }

    private static Map<String, Object> getDocumentToMap(Document document){
        Map<String, Object> map=new HashMap<>();
        document.forEach((k)->{
            map.put(k.name(),k.stringValue());
        });
        return map;
    }


    private static List<Document> getDocumentByScore(ScoreDoc[] scoreDocs,IndexSearcher indexSearcher) throws Exception{
        List<Document> documents=new ArrayList<>(scoreDocs.length);
        for (ScoreDoc scoreDoc : scoreDocs) {
            // 根据文档Id, 查询文档数据 -- 相当于关系数据库中根据主键Id查询数据
            Document doc = indexSearcher.doc(scoreDoc.doc);
            documents.add(doc);
        }
        return documents;
    }


    private static TopDocs getQueryDoc(IndexSearcher indexSearcher,String keyword,String field,Integer total) throws Exception{
        Query query=createQuery(keyword,field);
        TopDocs topDocs = indexSearcher.search(query, total);
        return topDocs;
    }

    private static Query createQuery(String keyword,String field) throws Exception{
        Analyzer analyzer = new StandardAnalyzer();
        QueryParser parser = new QueryParser(field, analyzer);
        return parser.parse(keyword);
    }

    private static IndexSearcher createIndexSearcher(String indexName) throws Exception{
        Directory directory=getDirectory(indexName);
        DirectoryReader ireader = DirectoryReader.open(directory);
        return new IndexSearcher(ireader);
    }



    /**
     * 批量添加
     * @param indexName
     * @param objectMaps
     * @throws Exception
     */
    public static void addListDocumentByIndexName(String indexName,List<Map<String, Object>> objectMaps) throws Exception{
        List<Document> documents=listToDocument(objectMaps);
        IndexWriter indexWriter=getIndexWriter(indexName);
        for (int i = 0; i < documents.size(); i++) {
            Document document=documents.get(i);
            indexWriter.addDocument(document);
        }
        indexWriter.close();
    }

    /**
     * 添加数据通过索引名称
     * @param indexName
     * @param document
     * @throws Exception
     */
    public static void addDocumentByIndexName(String indexName,Document document) throws Exception{
        IndexWriter indexWriter=getIndexWriter(indexName);
        indexWriter.addDocument(document);
        indexWriter.close();
    }

    private static List<Document> listToDocument(List<Map<String, Object>> mapList){
        List<Document> documents=new ArrayList<>(mapList.size());
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> objectMap=mapList.get(i);
            Document document=createDocument(objectMap);
            documents.add(document);
        }
        return documents;
    }

    private static IndexWriterConfig analyzerCreate(){
        Analyzer analyzer = new StandardAnalyzer();
        IndexWriterConfig indexConfig = new IndexWriterConfig( analyzer);
        return indexConfig;
    }

    private static Directory getDirectory(String indexName) throws Exception{
        File file=getFilePath(indexName);
        Directory directory = FSDirectory.open(Paths.get("C:\\Users\\xiong\\Desktop\\index"));
        return directory;
    }


    private static IndexWriter getIndexWriter(String indexName) throws Exception{
        Directory directory=getDirectory(indexName);
        System.out.println(directory);
        IndexWriterConfig indexWriterConfig=analyzerCreate();
        IndexWriter indexWriter=new IndexWriter(directory,indexWriterConfig);
        return indexWriter;
    }


    /**
     * 将map转为Document
     * @param stringObjectMap
     * @return
     */
    public static Document createDocument(Map<String, Object> stringObjectMap) {
        Document doc = new Document();
        for (Map.Entry<String, Object> objectEntry:stringObjectMap.entrySet()){
            doc.add(new StringField(objectEntry.getKey(), JSON.toJSONString(objectEntry.getValue()) , Field.Store.YES));
        }
        return doc;
    }


    /**
     * 为索引提供存储
     * @param indexPath
     * @return
     */
    private static File getFilePath(String indexPath){
        // File file= FileUtils.getFile("index"+File.separator+indexPath);
        File file= new File("C:\\Users\\xiong\\Desktop\\"+indexPath);
        return file;
    }
}
